package com.common.core;

import com.common.entity.Page;
import org.hibernate.query.internal.NativeQueryImpl;
import org.hibernate.transform.Transformers;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.io.Serializable;
import java.util.Calendar;
import java.util.List;
import java.util.Map;

public class BaseRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements BaseRepository<T, ID> {

    private final EntityManager entityManager;

    BaseRepositoryImpl(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager) {
        super(entityInformation, entityManager);
        this.entityManager = entityManager;
    }

    /**
     * 查询 返回集合
     *
     * @param sql
     * @return
     */
    public List<Map<String, Object>> execSql(String sql) {
        return execSql(sql, null);
    }

    /**
     * 查询 返回集合
     *
     * @param sql
     * @param objects 占位符参数数组
     * @return
     */
    public List<Map<String, Object>> execSql(String sql, Object[] objects) {
        Query query = entityManager.createNativeQuery(sql);
        if (objects != null && objects.length > 0) {
            for (int i = 0; i < objects.length; i++) {
                query.setParameter(i + 1, objects[i]);
            }
        }
        query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        return query.getResultList();
    }

    /**
     * @param page 自定义分页对象
     * @param sql  sql语句
     * @return Page分页对象
     */
    public Page execSqlPage(Page page, String sql) {
        Calendar staCal = Calendar.getInstance();
        Query sizeQuery = entityManager.createNativeQuery("select count(*) from (" + sql + ") c");
        Long count = Long.valueOf(sizeQuery.getSingleResult().toString());
        page.setCount(count);
        sql = sql + " limit " + (page.getCurr() - 1) * page.getLimit() + "," + page.getLimit();
        Query query = this.entityManager.createNativeQuery(sql);
        query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        System.out.println("sql = " + sql);
        page.setData(query.getResultList());
//        System.out.println("用时："+(Calendar.getInstance().getTimeInMillis()-staCal.getTimeInMillis()));
        return page;
    }

    /**
     * 查询 返回集合
     *
     * @param hql
     */
    public List<T> execHql(String hql) {
        Query query = entityManager.createQuery(hql);
        return query.getResultList();
    }

    /**
     * 查询 返回集合
     *
     * @param hql     hql
     * @param objects 占位符参数数组
     */
    public List<T> execHql(String hql, Object[] objects) {
        Query query = entityManager.createQuery(hql);
        if (objects != null && objects.length > 0) {
            for (int i = 0; i < objects.length; i++) {
                query.setParameter(i + 1, objects[i]);
            }
        }
        return query.getResultList();
    }

    /**
     * 查询 返回集合
     *
     * @param hql    hql
     * @param params 传参Map
     */
    public List<T> execHql(String hql, Map<String, Object> params) {
        Query query = entityManager.createQuery(hql);
        for (Map.Entry<String, Object> param : params.entrySet()) {
            query.setParameter(param.getKey(), param.getValue());
        }
        return query.getResultList();
    }

    public Page execHqlPage(Page page, String hql) {
        Query query = entityManager.createQuery(hql);
        String sizeHql = "";
        if (hql.trim().startsWith("from")) {
            sizeHql = "select count(*) " + hql;
        } else {
            sizeHql = "select count(*) from (" + hql + ")";
        }
        Long count = entityManager.createQuery(sizeHql, Long.class).getSingleResult();
        page.setCount(count);
        query.setFirstResult((page.getCurr() - 1) * page.getLimit());
        query.setMaxResults(page.getLimit());
        page.setData(query.getResultList());
        return page;
    }
}
